﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Google.KML;
using System.Drawing;

namespace MSAProject.AltitudeColor
{
    class AltitudeColorGenerator
    {
        public int MinHeight{ get; set; }
        public int MaxHeight{ get; set; }
        public int Alpha {get;set;}
        private int _numberOfSpans = 4;
        private Dictionary<string, ColorStyle> _styles;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="maxHeight">Maximum height of MSA</param>
        public AltitudeColorGenerator(int maxHeight) {
            initializeGenerator(maxHeight);
        }

        public AltitudeColorGenerator() {
            initializeGenerator(100);
        }

        public void test() {
            for (int i = 0; i < 300; i++) {
                System.Console.Out.WriteLine(getAltitudeSpan(i)+" : "+getAltitudeColor(i) + " : "+i);
            }
        }

        /// <summary>
        /// Metohod is used to assign a right color, which is depending on polygon height.
        /// </summary>
        /// <param name="polygonPM">Placemark with polygon geometry</param>
        public void AssignAltitude(gePlacemark polygonPM) {
            gePolygon polygon = (gePolygon)polygonPM.Geometry;
            List<geCoordinates> polygnCoordinates = polygon.OuterBoundaryIs.LinearRing.Coordinates;
            if (polygnCoordinates.Count > 0 && polygnCoordinates[0] != null)
            {
                int height = (int)polygnCoordinates[0].Altitude;
                Color color = getAltitudeColor(height);
                ColorStyle styleColor = new ColorStyle(color);
                if (_styles.ContainsKey(styleColor.StyleName) == false)
                {
                    _styles.Add(styleColor.StyleName, styleColor);
                }
                polygonPM.StyleUrl = "#"+styleColor.StyleName;
            }
        }

        /// <summary>
        /// Method adds styles definition to KML document. Method should be invoked after 
        /// all height were assigned.
        /// </summary>
        /// <param name="doc">KML document</param>
        public void AddStylesToKMLDoc(geDocument doc) {
            foreach (ColorStyle colorStyle in _styles.Values)
            {
                doc.StyleSelectors.Add(colorStyle.Style);
            }
        }

        /// <summary>
        /// Method calculates color based on height.
        /// </summary>
        /// <param name="height"></param>
        /// <returns></returns>
        private Color getAltitudeColor(double height)
        {
            //Normalizacja wysokości
            if (height > MaxHeight)
            {
                height = MaxHeight;
            }
            else if (height < MinHeight)
            {
                height = MinHeight;
            }

            int red = 0;
            int green = 0;
            int blue = 0;

            switch (getAltitudeSpan(height))
            {
                case 1:
                    red = 0;
                    green = getSignificantColorValue(height);
                    blue = 255;
                    break;
                case 2:
                    red = 0;
                    green = 255;
                    blue = 255 -getSignificantColorValue(height);
                    break;
                case 3:
                    red = getSignificantColorValue(height);
                    green = 255;
                    blue = 0;
                    break;
                case 4:
                    red = 255;
                    green = 255 - getSignificantColorValue(height);
                    blue = 0;
                    break;
            }
            System.Drawing.Color altitudeColor = System.Drawing.Color.FromArgb(Alpha, red, green, blue);
            return altitudeColor;
        }

        /// <summary>
        /// </summary>
        /// <param name="maxHeight">Maximum height of MSA</param>
        private void initializeGenerator(int maxHeight)
        {
            this.MaxHeight = maxHeight;
            MinHeight = 0;
            _styles = new Dictionary<string, ColorStyle>();
            Alpha = 0;
        }

        /// <summary>
        /// Method calculates significant color value.
        /// </summary>
        /// <param name="height">Height of MSA</param>
        /// <returns></returns>
        private int getSignificantColorValue(double height)
        {
            int spanHeight = MaxHeight - MinHeight;
            int singleSpanSize = spanHeight / _numberOfSpans;
            if (height == MaxHeight) height -= 0.00001f;
            double numberOfPercent = (height % singleSpanSize) * 100.0f / singleSpanSize ;
            numberOfPercent = numberOfPercent / 100.0f;
            return (int)(255 * numberOfPercent);
        }

        /// <summary>
        /// Method returns number of percent span where msa height is contained. 
        /// </summary>
        /// <param name="height"></param>
        /// <returns></returns>
        private int getAltitudeSpan(double height)
        {
            int spanHeight = MaxHeight - MinHeight;
            int singleSpanSize = spanHeight / _numberOfSpans;
            double numberOfPercent = height * 100.0f / spanHeight;

            if (numberOfPercent < 25.0f) return 1;
            if (numberOfPercent < 50.0f) return 2;
            if (numberOfPercent < 75.0f) return 3;
            return 4;
        }
    }
}
